<?php

class fixSchemaTask extends sfBaseTask {
    private static $BUILD_SCHEMA_COMMAND = 'symfony doctrine:build-schema';
    private static $CACHE_CLEAR_COMMAND = 'symfony cc';
    private static $SCHEMA_PATH = 'doctrine/schema.yml';
    private static $SFGUARD_KEYWORD = 'sfGuard';
    private static $TIMESTAMPABLE_KEYWORD = 'Timestampable';
    private static $ACTAS_KEYWORD = 'actAs';
    private static $SCHEMA_RELATIONS_KEYWORD = 'relations';
    private static $SCHEMA_COLUMNS_KEYWORD = 'columns';
    private static $SCHEMA_TIMESTAMPABLE_KEYWORDS = array('created_at', 'updated_at');

    protected function configure() {
        $this->namespace = 'doctrine';
        $this->name = 'build-fix-schema';
        $this->addOption('sf_guard_fix', null, sfCommandOption::PARAMETER_OPTIONAL, 'Fixes issues related to sfGuardPlugin', true);
        $this->addOption('timestampable_fix', null, sfCommandOption::PARAMETER_OPTIONAL, 'Fixes issues related to Timestampable tables', true);
    }

    protected function execute($arguments = array(), $options = array()) {
        shell_exec(self::$BUILD_SCHEMA_COMMAND);

        $schemaFile = sfConfig::get("sf_config_dir") . "/" . self::$SCHEMA_PATH;
        if(file_exists($schemaFile) && is_readable($schemaFile) && is_writable($schemaFile)) {
            $yaml = new sfYaml();
            $currSchema = $yaml->load($schemaFile);
            if(count($currSchema)) {
                $tmpSchema = base64_encode(serialize($currSchema));
                $newSchema = array();
                foreach($currSchema as $tableName => $table) {
                    if($options["sf_guard_fix"] !== "false") {
                        if(strtoupper(substr($tableName, 0, strlen(self::$SFGUARD_KEYWORD))) === strtoupper(self::$SFGUARD_KEYWORD)) {
                            continue;
                        }

                        if(isset($table[self::$SCHEMA_RELATIONS_KEYWORD])) {
                            $newRelations = array();
                            foreach($table[self::$SCHEMA_RELATIONS_KEYWORD] as $relationName => $relation) {
                                if(strtoupper(substr($relationName, 0, strlen(self::$SFGUARD_KEYWORD))) === strtoupper(self::$SFGUARD_KEYWORD) && substr($relationName, 0, 1) === 'S') {
                                    $relationName[0] = 's';
                                }
                                $newRelations[$relationName] = $relation;
                            }
                            $table[self::$SCHEMA_RELATIONS_KEYWORD] = $newRelations;
                        }
                    }

                    if($options["timestampable_fix"] !== "false") {
                        $hasTimestampableColumns = false;
                        if(isset($table[self::$SCHEMA_COLUMNS_KEYWORD])) {
                            $newColumns = array();
                            foreach($table[self::$SCHEMA_COLUMNS_KEYWORD] as $columnName => $column) {
                                if(!in_array($columnName, self::$SCHEMA_TIMESTAMPABLE_KEYWORDS)) {
                                    $newColumns[$columnName] = $column;
                                } else {
                                    $hasTimestampableColumns = true;
                                }
                            }
                            $table[self::$SCHEMA_COLUMNS_KEYWORD] = $newColumns;
                        }
                        if($hasTimestampableColumns) {
                            $table[self::$ACTAS_KEYWORD] = array(self::$TIMESTAMPABLE_KEYWORD => NULL);
                        }
                    }

                    $newSchema[$tableName] = $table;
                }

                if($tmpSchema !== base64_encode(serialize($newSchema))) {
                    $newSchema = $yaml->dump($newSchema, 99);
                    if(file_put_contents($schemaFile, $newSchema)) {
                        $this->log("Schema fixed!");
                    } else {
                        $this->log("Schema cannot be overwritten. Schema was not fixed.");
                    }

                } else {
                    $this->log("Nothing to fix. Schema was not modified.");
                }
            } else {
                $this->log("Schema cannot be loaded.");
            }
            unset($yaml);
        } else {
            $this->log("Schema cannot be found or not accessible: $schemaFile");
        }
        shell_exec(self::$CACHE_CLEAR_COMMAND);
    }
}
?>